package simpledb.record;

import static simpledb.sql.Types.INTEGER;
import static simpledb.file.Page.*;
import static simpledb.record.RecordPage.*;
import simpledb.file.Page;
import simpledb.buffer.PageFormatter;


/**
 * An object that can format a page to look like a block of 
 * empty records.
 * @author Conan
 *
 */
class RecordFormatter implements PageFormatter {
	private TableInfo ti;
	private int base;
	private int nextblk;
	private int prevblk;
	private int holehead;
	private int usehead;
	private int usetail;
	private final int REC_SIZE;

	/**
	 * Creates a formatter for a new page of a table.
	 * @param ti the table's metadata
	 */
	public RecordFormatter(TableInfo ti, int remain, int prev) {
		this.ti = ti;
		base = remain+RECPAGE_HEAD_SIZE;
		nextblk = -1;
		prevblk = prev;
		holehead = 0;
		usehead = -1;
		usetail = -1;
		REC_SIZE = ti.recordLength()+REC_HEAD_SIZE;
	}

	/** 
	 * Formats the page by allocating as many record slots
	 * as possible, given the record length.
	 * Each record slot is assigned a flag of EMPTY.
	 * Each integer field is given a value of 0, and
	 * each string field is given a value of "".
	 * @see simpledb.buffer.PageFormatter#format(simpledb.file.Page)
	 */
	public void format(Page page) {
		int pos = RECPAGE_HEAD_SIZE;
		int currentrec = 0;
		boolean hashole = false;
		page.setInt(BASE_OFFSET, base);
		page.setInt(NEXTBLK_OFFSET, nextblk);
		page.setInt(PREVBLK_OFFSET, prevblk);
		page.setInt(HOLEHEAD_OFFSET, holehead);
		page.setInt(USEHEAD_OFFSET, usehead);
		page.setInt(USETAIL_OFFSET, usetail);

		while(pos != BLOCK_SIZE){
			if(pos >= base){
				if(pos + REC_SIZE >= BLOCK_SIZE)
					page.setInt(pos + NEXTREC_OFFSET, -1);
				else
					page.setInt(pos + NEXTREC_OFFSET, ++currentrec);
				hashole = true;
			}
			pos += makeDefaultRecord(page, pos);
		}
		if(! hashole){
			holehead = -1;
			page.setInt(HOLEHEAD_OFFSET, holehead);
		}
	}
	
	private int makeDefaultRecord(Page page, int pos) {
		int size = REC_SIZE;
		for (String fldname : ti.schema().fields()) {
			int offset = ti.offset(fldname);
			int realpos;
			// base > BLOCK_SIZE
			if(base - pos>0){
				realpos = base - (ti.recordLength() - offset);
				if( pos > realpos ) continue;
			}
			else 
				realpos = pos + REC_HEAD_SIZE + offset;
			
			if( realpos >= BLOCK_SIZE ) continue;
						
			if (ti.schema().type(fldname) == INTEGER)
				page.setInt(realpos, 0x55);
			else
				page.setString(realpos, "my name is conan");
		}
		if(base - pos >0){
			if( base <= BLOCK_SIZE )
				size = base - pos;
			else
				size = BLOCK_SIZE - pos;
		}
		else if(pos + REC_SIZE > BLOCK_SIZE)
			size = BLOCK_SIZE - pos;
		
		return size;
	}
}
